__author__ = 'shawhen'

import ctypes

from . import winnt

from .. import WinNT
from .. import WinDef
from .. import Kernel32

from ..shared import minwindef as m_shared_minwindef


class STARTUPINFO(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ("cb", WinDef.DWORD),
        ("lpReserved", winnt.LPWSTR),
        ("lpDesktop", winnt.LPWSTR),
        ("lpTitle", winnt.LPWSTR),
        ("dwX", WinDef.DWORD),
        ("dwY", WinDef.DWORD),
        ("dwXSize", WinDef.DWORD),
        ("dwYSize", WinDef.DWORD),
        ("dwXCountChars", WinDef.DWORD),
        ("dwYCountChars", WinDef.DWORD),
        ("dwFillAttribute", WinDef.DWORD),
        ("dwFlags", WinDef.DWORD),
        ("wShowWindow", m_shared_minwindef.WORD),
        ("cbReserved2", m_shared_minwindef.WORD),
        ("lpReserved2", m_shared_minwindef.LPBYTE),
        ("hStdInput", WinNT.HANDLE),
        ("hStdOutput", WinNT.HANDLE),
        ("hStdError", WinNT.HANDLE)
    ]


class PROCESS_INFORMATION(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ("hProcess", WinNT.HANDLE),
        ("hThread", WinNT.HANDLE),
        ("dwProcessId", WinDef.DWORD),
        ("dwThreadId", WinDef.DWORD)
    ]


def CreateProcess(application_name, command_line, process_attributes, thread_attributes,
                  bInheritHandles, dwCreationFlags, environment, current_directory, startup_info,
                  process_inforamtion):
    """
    :param application_name None将代表NULL
    :param command_line None将代表NULL
    :param process_attributes None将代表NULL（不是结构体指针）
    :param thread_attributes None将代表NULL（不是结构体指针）
    :param bInheritHandles True==TRUE, False==FALSE
    :param dwCreationFlags
    :param environment None==NULL（不是结构体指针）
    :param current_directory None==NULL
    :param startup_info None==NULL（不是结构体指针）
    :param process_inforamtion None==NULL（不是结构体指针）
    :return True/False
    """
    from ....cstd import stdio

    if application_name is None:
        application_name = stdio.NULL
    if command_line is None:
        command_line = stdio.NULL
    if process_attributes is None:
        process_attributes = stdio.NULL
    else:
        process_attributes = ctypes.byref(process_attributes)
    if thread_attributes is None:
        thread_attributes = stdio.NULL
    else:
        thread_attributes = ctypes.byref(thread_attributes)
    if bInheritHandles is True:
        bInheritHandles = m_shared_minwindef.TRUE
    elif bInheritHandles is False:
        bInheritHandles = m_shared_minwindef.FALSE
    if environment is None:
        environment = stdio.NULL
    else:
        environment = ctypes.byref(environment)
    if current_directory is None:
        current_directory = stdio.NULL
    if startup_info is None:
        startup_info = stdio.NULL
    else:
        startup_info = ctypes.byref(startup_info)
    if process_inforamtion is None:
        process_inforamtion = stdio.NULL
    else:
        process_inforamtion = ctypes.byref(process_inforamtion)
    result = Kernel32.Kernel32_dll.CreateProcessW(application_name, command_line, process_attributes, thread_attributes,
                                                bInheritHandles, dwCreationFlags, environment, current_directory,
                                                startup_info, process_inforamtion)
    if result == m_shared_minwindef.FALSE:
        result = False
    elif result == m_shared_minwindef.TRUE:
        result = True
    return result


def TerminateProcess(hProcess, exit_code):
    """
    :return True/False
    """
    uExitCode = m_shared_minwindef.UINT(exit_code)
    result = Kernel32.Kernel32_dll.TerminateProcess(hProcess, uExitCode)
    if result == m_shared_minwindef.FALSE:
        result = False
    elif result == m_shared_minwindef.TRUE:
        result = True
    return result


def GetExitCodeProcess(hProcess):
    """
    :return (True/False, ExitCode)
    """
    exit_code = m_shared_minwindef.DWORD(0)
    result = Kernel32.Kernel32_dll.GetExitCodeProcess(hProcess, ctypes.byref(exit_code))

    if result == m_shared_minwindef.FALSE:
        result = False
    elif result == m_shared_minwindef.TRUE:
        result = True
    return result, exit_code.value